package freakin.wify;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.Projection;

public class Map extends MapActivity {

	private static final String TAG = "Map";

	MapView mapView;
	MapManager mapManager;

	Overlay networkOverlay;

	WifiApp app;

	private MyLocationOverlay myLocation;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.d(TAG, "creating map activity");
		setContentView(R.layout.map);
		mapView = (MapView) findViewById(R.id.mapview);
		mapView.setBuiltInZoomControls(true);

		app = (WifiApp) getApplication();

		List<Overlay> mapOverlays = mapView.getOverlays();
		Drawable drawable = this.getResources().getDrawable(
				R.drawable.androidmarker);

		mapManager = new MapManager(drawable, this);

		mapOverlays.add(mapManager);

		myLocation = new MyLocationOverlay(this, mapView);
		myLocation.enableMyLocation();
		myLocation.enableCompass();

		mapOverlays.add(myLocation);

		updatePositions();

		myLocation.runOnFirstFix(new Runnable() {
			public void run() {
				String loc = "we have a location, executing AnimateTo()."
						+ myLocation.getMyLocation().toString();
				Log.i(TAG, loc);

				MapController mapController = mapView.getController();
				mapController.animateTo(myLocation.getMyLocation());
				mapController.setZoom(15);
			}
			
		});

		Log.d(TAG, "map activity created");
	}

	private void updatePositions() {
		Log.d(TAG, "updatePositions() started");
		changeNetworkPosition(app.nearestNetwork);
		if (myLocation.getMyLocation() != null
				&& mapManager.networkOverlay != null) {
			DrawPath(myLocation.getMyLocation(),
					mapManager.networkOverlay.getPoint(), Color.BLUE, mapView);
		}

		mapView.invalidate();
		Log.d(TAG, "updatePositions() completed");
	}

	@Override
	public void onResume() {
		super.onResume();
		updatePositions();
	}

	public void changeNetworkPosition(Network network) {
		Log.d(TAG, "updating network position");
		if (network != null) {
			GeoPoint point = new GeoPoint((int) (network.latitude * 1E6),
					(int) (network.longitude * 1e6));
			OverlayItem networkPosition = new OverlayItem(point,
					"Network's location", "Network: " + network.ssid);
			Log.d(TAG, "setting network position to: " + "("
					+ (int) (network.latitude * 1E6) + ", "
					+ (int) (network.longitude * 1e6) + ").");
			mapManager.setNetworkOverlay(networkPosition);
			Log.d(TAG, "updating network position completed");
		} else
			Log.d(TAG, "Network is NULL! ! !");
	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	/**
	 * Code drawing a route between two POIs. Copy paste from:
	 * http://stackoverflow
	 * .com/questions/4408671/android-draw-route-on-a-mapview-with-twoo-poi-s
	 * 
	 * @param src
	 * @param dest
	 * @param color
	 * @param mMapView01
	 */
	private void DrawPath(GeoPoint src, GeoPoint dest, int color,
			MapView mMapView01) {

		// connect to map web service
		StringBuilder urlString = new StringBuilder();
		urlString.append("http://maps.google.com/maps?f=d&hl=en");
		urlString.append("&saddr=");// from
		urlString.append(Double.toString((double) src.getLatitudeE6() / 1.0E6));
		urlString.append(",");
		urlString
				.append(Double.toString((double) src.getLongitudeE6() / 1.0E6));
		urlString.append("&daddr=");// to
		urlString
				.append(Double.toString((double) dest.getLatitudeE6() / 1.0E6));
		urlString.append(",");
		urlString
				.append(Double.toString((double) dest.getLongitudeE6() / 1.0E6));
		urlString.append("&ie=UTF8&0&om=0&output=kml");
		Log.d("xxx", "URL=" + urlString.toString());

		// System.out.println(urlString);
		// get the kml (XML) doc. And parse it to get the coordinates(direction
		// route).
		Document doc = null;
		HttpURLConnection urlConnection = null;
		URL url = null;
		try {
			url = new URL(urlString.toString());
			urlConnection = (HttpURLConnection) url.openConnection();
			urlConnection.setRequestMethod("GET");
			urlConnection.setDoOutput(true);
			urlConnection.setDoInput(true);
			urlConnection.connect();

			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			doc = db.parse(urlConnection.getInputStream());

			if (doc.getElementsByTagName("GeometryCollection").getLength() > 0) {
				// String path =
				// doc.getElementsByTagName("GeometryCollection").item(0).getFirstChild().getFirstChild().getNodeName();
				String path = doc.getElementsByTagName("GeometryCollection")
						.item(0).getFirstChild().getFirstChild()
						.getFirstChild().getNodeValue();
			//	Log.d("xxx", "path=" + path);
				String[] pairs = path.split(" ");
				String[] lngLat = pairs[0].split(","); // lngLat[0]=longitude
														// lngLat[1]=latitude
														// lngLat[2]=height
				// src
				GeoPoint startGP = new GeoPoint(
						(int) (Double.parseDouble(lngLat[1]) * 1E6),
						(int) (Double.parseDouble(lngLat[0]) * 1E6));
				// mMapView01.getOverlays().add(overlayitem);
				GeoPoint gp1;
				GeoPoint gp2 = startGP;
				for (int i = 1; i < pairs.length; i++) // the last one would be
														// crash
				{
					lngLat = pairs[i].split(",");
					gp1 = gp2;
					// watch out! For GeoPoint, first:latitude, second:longitude
					gp2 = new GeoPoint(
							(int) (Double.parseDouble(lngLat[1]) * 1E6),
							(int) (Double.parseDouble(lngLat[0]) * 1E6));
					mMapView01.getOverlays().add(
							new MapRouteOverlay(gp1, gp2, 2, color));
			//		Log.d("xxx", "pair:" + pairs[i]);
				}
				// mMapView01.getOverlays().add(new MapRouteOverlay(dest,dest,
				// 3)); // use the default color
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}

	}

	/**
	 * Code drawing a route between two POIs. Copy paste from:
	 * http://stackoverflow
	 * .com/questions/4408671/android-draw-route-on-a-mapview-with-twoo-poi-s
	 * 
	 */
	public class MapRouteOverlay extends Overlay {

		private GeoPoint gp1;
		private GeoPoint gp2;

		private int mode = 0;
		private int defaultColor;

		public MapRouteOverlay(GeoPoint gp1, GeoPoint gp2, int mode) // GeoPoint
																		// is a
																		// int.
																		// (6E)
		{
			this.gp1 = gp1;
			this.gp2 = gp2;
			this.mode = mode;
			defaultColor = 999; // no defaultColor

		}

		public MapRouteOverlay(GeoPoint gp1, GeoPoint gp2, int mode,
				int defaultColor) {
			this.gp1 = gp1;
			this.gp2 = gp2;
			this.mode = mode;
			this.defaultColor = defaultColor;
		}

		public int getMode() {
			return mode;
		}

		public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
				long when) {
			Projection projection = mapView.getProjection();
			if (shadow == false) {

				Paint paint = new Paint();
				paint.setAntiAlias(true);
				Point point = new Point();
				projection.toPixels(gp1, point);

				if (mode == 2) {
					if (defaultColor == 999)
						paint.setColor(Color.RED);
					else
						paint.setColor(defaultColor);
					Point point2 = new Point();
					projection.toPixels(gp2, point2);
					paint.setStrokeWidth(5);
					paint.setAlpha(120);
					canvas.drawLine(point.x, point.y, point2.x, point2.y, paint);
				}

			}
			return super.draw(canvas, mapView, shadow, when);
		}
	}

}
